package com.stooscloud.provider.impl;

import com.stooscloud.AESUtil;
import com.stooscloud.BeanToMapUtil;
import com.stooscloud.JacksonUtil;
import com.stooscloud.RedisKeyUtil;
import com.stooscloud.base.exception.BusinessException;
import com.stooscloud.provider.builder.Builder;
import com.stooscloud.provider.config.TransInitRunner;
import com.stooscloud.provider.impl.doman.CopyGeoA2;
import com.stooscloud.provider.impl.doman.GeoA2;
import com.stooscloud.provider.impl.factory.GeoA2BuilderFactory;
import com.stooscloud.provider.model.dto.response.geo.GeoLoginRespose;
import com.stooscloud.provider.model.dto.response.geoquery.GeoQueryRespose;
import com.stooscloud.provider.service.GeoFeignApi;
import com.stooscloud.wrapper.WrapMapper;
import com.stooscloud.wrapper.Wrapper;
import config.properties.WsProperties;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class GeoA2Builder implements Builder<GeoA2> {
    @Autowired
    private TransInitRunner transInitRunner;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    WsProperties wsProperties;
    @Autowired
    GeoA2BuilderFactory geoA2BuilderFactory;
    @Resource
    GeoFeignApi geoFeignApi;

    private GeoA2 geoA2;
    private CopyGeoA2 copyGeoA2;
    private GeoQueryRespose geoQueryRespose;
    @Override
    public GeoA2 createDoman(Object obj) throws BusinessException {
        try {
            this.geoA2 = geoA2BuilderFactory.builderObj(obj);
            log.info("接收前端的报文信息:{}",this.geoA2.toString());
        }catch (Exception ex){
            if(ex instanceof BusinessException){
                throw ex;
            }else {
                throw new BusinessException(1002,"解析上传报文失败!");
            }
        }
        return null;
    }

    @Override
    public void handler() throws BusinessException {
        encrypt();
    }

    private void encrypt(){
        if ("1".equals(wsProperties.getGeo().getEncrypted())){
            geoA2.setInnerIfType(AESUtil.encrypt(geoA2.getInnerIfType(),wsProperties.getGeo().getKey()));
            geoA2.setAuthCode(AESUtil.encrypt(geoA2.getAuthCode(),wsProperties.getGeo().getKey()));
            geoA2.setRealName(AESUtil.encrypt(geoA2.getRealName(),wsProperties.getGeo().getKey()));
            geoA2.setCid(AESUtil.encrypt(geoA2.getCid(),wsProperties.getGeo().getKey()));
            geoA2.setIdNumber(AESUtil.encrypt(geoA2.getIdNumber(),wsProperties.getGeo().getKey()));
        }

    }
    @Override
    public void idBus() throws BusinessException {
        if (transInitRunner.busMap.get(geoA2.getSystemId()+"_"+geoA2.getTranCode())){
            log.info("开始业务逻辑处理");
            String tokenId = getToken();
            geoA2.setTokenId(tokenId);
        }
    }

    private String getToken(){
        String tokenId = (String) redisTemplate.opsForValue().get(RedisKeyUtil.getGeoTokenId());
        if(StringUtils.isBlank(tokenId)){
            synchronized (geoFeignApi){
                tokenId = (String) redisTemplate.opsForValue().get(RedisKeyUtil.getGeoTokenId());
                if(StringUtils.isBlank(tokenId)){
                    Map userMap = new HashMap();
                    if("1".equals(wsProperties.getGeo().getEncrypted())){
                        userMap.put("username", AESUtil.encrypt(wsProperties.getGeo().getUserName(),wsProperties.getGeo().getKey()));
                        userMap.put("password",AESUtil.encrypt(wsProperties.getGeo().getPassWord(),wsProperties.getGeo().getKey()));
                        userMap.put("dsign",AESUtil.encrypt(wsProperties.getGeo().getDsign(),wsProperties.getGeo().getKey()));
                    }else {
                        userMap.put("username",wsProperties.getGeo().getUserName());
                        userMap.put("password",wsProperties.getGeo().getPassWord());
                        userMap.put("dsign",wsProperties.getGeo().getDsign());
                    }
                    userMap.put("uno",wsProperties.getGeo().getUno());
                    userMap.put("encrypted",wsProperties.getGeo().getEncrypted());
                    try {
                        GeoLoginRespose geoLoginRespose = getTokenid(userMap);
                        if (geoLoginRespose !=null && "200".equals(geoLoginRespose.getCode())){
                            tokenId = geoLoginRespose.getTokenId();
                            redisTemplate.opsForValue().set(RedisKeyUtil.getGeoTokenId(),tokenId,3600, TimeUnit.SECONDS);
                        }else {
                            throw new BusinessException(1009,"获取tokenId失败!");
                        }
                    }catch (Exception e){
                        throw new BusinessException(1009,"获取tokenId失败!");
                    }
                }
            }
        }
        return tokenId;
    }

    @Override
    public void call() throws BusinessException {
        try {
            copyGeoA2 = new CopyGeoA2();
            BeanUtils.copyProperties(geoA2,copyGeoA2);
            Map geoMap = BeanToMapUtil.beanToMap(copyGeoA2);
            geoQueryRespose = query(geoMap);
        } catch (Exception e) {
            log.error("请求服务端失败",e);
            if (geoQueryRespose == null){
                geoQueryRespose = new GeoQueryRespose("10009","系统错误");
            }
        }
    }

    @Override
    public Wrapper installWrapper() throws BusinessException {
        Wrapper wrapper = WrapMapper.ok(geoQueryRespose);
        updateRedisMsg();
        return wrapper;
    }

    private void updateRedisMsg(){
        redisTemplate.opsForValue().set(RedisKeyUtil.getGeoTokenId(geoQueryRespose.getCode(),geoA2.getAuthCode()),geoQueryRespose);
    }

    private GeoLoginRespose getTokenid(Map userMap){
        GeoLoginRespose geoLoginRespose = null;
        try {
            String AESValue = geoFeignApi.login(userMap);
            log.info("获取返回信息【{}】!",AESValue);
            String jsonValue = AESUtil.decrypt(AESValue,wsProperties.getGeo().getKey());
            geoLoginRespose = JacksonUtil.parseJson(jsonValue,GeoLoginRespose.class);
            log.info("获取tokenId为：{}!",geoLoginRespose.getTokenId());
        } catch (Exception e) {
            log.error("获取tokenId失败!",e);
            throw new BusinessException(1009,"获取tokenId失败!");
        }
        return geoLoginRespose;
    }

    private GeoQueryRespose query(Map geoMap){
        GeoQueryRespose geoQueryRespose = null;
        try {
            log.info("geoMapSize【{}】!",geoMap.size());
            log.info("geoMap【{}】!",geoMap);
            String AESValue = geoFeignApi.queryUnify(geoMap);
            log.info("获取返回信息【{}】!",AESValue);
            String jsonValue = AESUtil.decrypt(AESValue,wsProperties.getGeo().getKey()).toLowerCase();
            log.info("获取返回报文{}",jsonValue);
            geoQueryRespose = JacksonUtil.parseJson(jsonValue,GeoQueryRespose.class);
            log.info("获取返回码:{},返回信息:{}",geoQueryRespose.getCode(),geoQueryRespose.getMsg());
        } catch (Exception e) {
            log.error("查询信息失败!",e);
            throw new BusinessException(1009,"查询信息失败!");
        }
        return geoQueryRespose;
    }
}
